/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

using System;
using System.Collections.Generic;

namespace FaceCat {
    /// <summary>
    /// 日历模式
    /// </summary>
    public enum FCCalendarMode {
        /// <summary>
        /// 选择日
        /// </summary>
        Day,
        /// <summary>
        /// 选择月
        /// </summary>
        Month,
        /// <summary>
        /// 选择年
        /// </summary>
        Year
    }

    /// <summary>
    /// 日历视图
    /// </summary>
    public partial class FCCalendar : FCView {
        /// <summary>
        /// 创建日历视图
        /// </summary>
        public FCCalendar() {
            m_years = new CYears();
            m_size = new FCSize(200, 200);
        }

        /// <summary>
        /// 当前的月份
        /// </summary>
        public int m_month;

        /// <summary>
        /// 是否显示周末
        /// </summary>
        public bool m_showWeekend = true;

        /// <summary>
        /// 秒表ID
        /// </summary>
        private int m_timerID = getNewTimerID();

        /// <summary>
        /// 当前的年份
        /// </summary>
        public int m_year;

        public DayDiv m_dayDiv;

        /// <summary>
        /// 获取日期层
        /// </summary>
        public virtual DayDiv getDayDiv()
        {
            return m_dayDiv;
        }

        /// <summary>
        /// 设置日期层
        /// </summary>
        public virtual void setDayDiv(DayDiv dayDiv)
        {
            m_dayDiv = dayDiv;
        }

        public HeadDiv m_headDiv;

        /// <summary>
        /// 获取头部层
        /// </summary>
        public virtual HeadDiv getHeadDiv()
        {
            return m_headDiv;
        }

        /// <summary>
        /// 设置头部层
        /// </summary>
        public virtual void setHeadDiv(HeadDiv headDiv)
        {
            m_headDiv = headDiv;
        }

        public FCCalendarMode m_mode = FCCalendarMode.Day;

        /// <summary>
        /// 获取或设置日历的模式
        /// </summary>
        public virtual FCCalendarMode getMode() {
            return m_mode;
        }

        /// <summary>
        /// 设置模式
        /// </summary>
        public virtual void setMode(FCCalendarMode value) {
            if (m_mode != value) {
                FCCalendarMode oldMode = m_mode;
                m_mode = value;
                //月
                if (m_mode == FCCalendarMode.Month) {
                    if (m_dayDiv != null) {
                        m_dayDiv.hide();
                    }
                    if (m_yearDiv != null) {
                        m_yearDiv.hide();
                    }
                    if (m_monthDiv == null) {
                        m_monthDiv = createMonthDiv();
                    }
                    if (oldMode == FCCalendarMode.Day) {
                        m_monthDiv.selectYear(m_year);
                    }
                    m_monthDiv.show();
                }
                    //年
                else if (m_mode == FCCalendarMode.Year) {
                    if (m_dayDiv != null) {
                        m_dayDiv.hide();
                    }
                    int startYear = m_year;
                    if (m_monthDiv != null) {
                        startYear = m_monthDiv.getYear();
                        m_monthDiv.hide();
                    }
                    if (m_yearDiv == null) {
                        m_yearDiv = createYearDiv();
                    }
                    m_yearDiv.selectStartYear(startYear);
                    m_yearDiv.show();
                } else {
                    if (m_monthDiv != null) {
                        m_monthDiv.hide();
                    }
                    if (m_yearDiv != null) {
                        m_yearDiv.hide();
                    }
                    m_dayDiv.show();
                }
            }
        }

        /// <summary>
        /// 获取月份
        /// </summary>
        public virtual CMonth getMonth()
        {
            return m_years.getYear(m_year).getMonths().get(m_month);
        }

        /// <summary>
        /// 设置月份
        /// </summary>
        public virtual void setMonth(CMonth value)
        {
            m_year = value.getYear();
            m_month = value.getMonth();
            update();
        }

        /// <summary>
        /// 月份层
        /// </summary>
        public MonthDiv m_monthDiv;

        /// <summary>
        /// 获取或设置月份层
        /// </summary>
        public virtual MonthDiv getMonthDiv()
        {
            return m_monthDiv;
        }

        /// <summary>
        /// 获取或设置月份层
        /// </summary>
        public virtual void setMonthDiv(MonthDiv value)
        {
            m_monthDiv = value;
        }

        public CDay m_selectedDay;

        /// <summary>
        /// 获取选中日期
        /// </summary>
        public virtual CDay getSelectedDay()
        {
            return m_selectedDay;
        }

        /// <summary>
        /// 设置选中日期
        /// </summary>
        public virtual void setSelectedDay(CDay value)
        {
            if (m_selectedDay != value)
            {
                m_selectedDay = value;
                if (m_dayDiv != null)
                {
                    m_dayDiv.selectedDay(m_selectedDay);
                }
                invalidate();
                onSelectedTimeChanged();
            }
        }

        public TimeDiv m_timeDiv;

        /// <summary>
        /// 获取时间层
        /// </summary>
        public virtual TimeDiv getTimeDiv()
        {
            return m_timeDiv;
        }

        /// <summary>
        /// 设置时间层
        /// </summary>
        public virtual void setTimeDiv(TimeDiv value)
        {
            m_timeDiv = value;
        }

        public bool m_useAnimation;

        /// <summary>
        /// 获取是否使用动画
        /// </summary>
        public virtual bool useAnimation()
        {
            return m_useAnimation;
        }

        /// <summary>
        /// 设置是否使用动画
        /// </summary>
        public virtual void setUseAnimation(bool value)
        {
            m_useAnimation = value;
            if (m_useAnimation)
            {
                startTimer(m_timerID, 20);
            }
            else
            {
                stopTimer(m_timerID);
            }
        }

        public YearDiv m_yearDiv;

        /// <summary>
        /// 获取年份层
        /// </summary>
        public virtual YearDiv getYearDiv()
        {
            return m_yearDiv;
        }

        /// <summary>
        /// 设置年份层
        /// </summary>
        public virtual void setYearDiv(YearDiv value)
        {
            m_yearDiv = value;
        }

        public CYears m_years;

        /// <summary>
        /// 获取日历
        /// </summary>
        public virtual CYears getYears()
        {
            return m_years;
        }

        /// <summary>
        /// 设置日历
        /// </summary>
        public virtual void setYears(CYears value)
        {
            m_years = value;
            update();
            setSelectedDay(getMonth().getDays().get(1));
        }

        /// <summary>
        /// 销毁事件
        /// </summary>
        public override void delete() {
            if (!isDeleted()) {
                if (m_dayDiv != null) {
                    m_dayDiv.delete();
                }
                if (m_monthDiv != null) {
                    m_monthDiv.delete();
                }
                if (m_yearDiv != null) {
                    m_yearDiv.delete();
                }
                stopTimer(m_timerID);
            }
            base.delete();
        }

        /// <summary>
        /// 获取视图类型
        /// </summary>
        /// <returns>视图类型</returns>
        public override String getViewType() {
            return "Calendar";
        }

        /// <summary>
        /// 获取事件名称列表
        /// </summary>
        /// <returns>名称列表</returns>
        public override ArrayList<String> getEventNames() {
            ArrayList<String> eventNames = base.getEventNames();
            eventNames.AddRange(new String[] { "SelectedTimeChanged" });
            return eventNames;
        }

        /// <summary>
        /// 根据年月获取上个月
        /// </summary>
        /// <param name="year">年</param>
        /// <param name="month">月</param>
        /// <returns>上个月</returns>
        public CMonth getLastMonth(int year, int month) {
            int lastMonth = month - 1;
            int lastYear = year;
            if (lastMonth == 0) {
                lastMonth = 12;
                lastYear -= 1;
            }
            return m_years.getYear(lastYear).getMonths().get(lastMonth);
        }

        /// <summary>
        /// 获取下个月
        /// </summary>
        /// <param name="year">年</param>
        /// <param name="month">月</param>
        /// <returns>下个月</returns>
        public CMonth getNextMonth(int year, int month) {
            int nextMonth = month + 1;
            int nextYear = year;
            if (nextMonth == 13) {
                nextMonth = 1;
                nextYear += 1;
            }
            return m_years.getYear(nextYear).getMonths().get(nextMonth);
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        /// <param name="type">类型</param>
        public override void getAttribute(String name, ref String value, ref String type) {
            if (name == "selectedday") {
                type = "text";
                value = String.Format("{0}-{1}-{2}", m_year, m_month, m_selectedDay.getDay());
            } else if (name == "useanimation") {
                type = "bool";
                value = FCTran.boolToStr(useAnimation());
            } else {
                base.getAttribute(name, ref value, ref type);
            }
        }

        /// <summary>
        /// 获取属性名称列表
        /// </summary>
        /// <returns>属性名称列表</returns>
        public override ArrayList<String> getAttributeNames() {
            ArrayList<String> attributeNames = base.getAttributeNames();
            attributeNames.add("SeletedDay");
            attributeNames.add("UseAnimation");
            return attributeNames;
        }

        /// <summary>
        /// 回到上个月
        /// </summary>
        public void goLastMonth() {
            setSelectedDay(getLastMonth(m_year, m_month).getDays().get(1));
        }

        /// <summary>
        /// 前往下个月
        /// </summary>
        public void goNextMonth() {
            setSelectedDay(getNextMonth(m_year, m_month).getDays().get(1));
        }

        /// <summary>
        /// 触摸点击方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onClick(FCTouchInfo touchInfo) {
            base.onClick(touchInfo);
            if (m_dayDiv != null) {
                m_dayDiv.onClick(touchInfo);
                if (m_dayDiv.m_dayButtons[0].isVisible()) {
                    FCMenu menu = getParent() as FCMenu;
                    if (menu != null && menu.canPopup()) {
                        menu.hide();
                        menu.invalidate();
                    }
                }
            }
            if (m_monthDiv != null) {
                m_monthDiv.onClick(touchInfo);
            }
            if (m_yearDiv != null) {
                m_yearDiv.onClick(touchInfo);
            }
        }

        /// <summary>
        /// 视图被添加事件
        /// </summary>
        public override void onLoad() {
            base.onLoad();
            FCHost host = getNative().getHost();
            if (m_dayDiv == null) {
                m_dayDiv = createDayDiv();
            }
            if (m_timeDiv == null) {
                m_timeDiv = createTimeDiv();
            }
            if (m_headDiv == null) {
                m_headDiv = createHeadDiv();
                addView(m_headDiv);
            }
            if (m_useAnimation) {
                startTimer(m_timerID, 20);
            } else {
                stopTimer(m_timerID);
            }
            if (m_years != null && m_year == 0 && m_month == 0) {
                DateTime date = DateTime.Now;
                m_year = date.Year;
                m_month = date.Month;
                setSelectedDay(m_years.getYear(m_year).getMonths().get(m_month).getDays().get(date.Day));
            }
        }

        /// <summary>
        /// 键盘方法
        /// </summary>
        /// <param name="key">按键</param>
        public override void onKeyDown(char key) {
            base.onKeyDown(key);
            FCHost host = getNative().getHost();
            if (!host.isKeyPress(0x10) && !host.isKeyPress(0x11) && !host.isKeyPress(0x12)) {
                CMonth thisMonth = getMonth();
                CMonth lastMonth = getLastMonth(m_year, m_month);
                CMonth nextMonth = getNextMonth(m_year, m_month);
                int today = m_selectedDay.getDay();
                if (key >= 37 && key <= 40) {
                    switch ((int)key) {
                        case 37:
                            if (m_selectedDay == thisMonth.getFirstDay()) {
                                setSelectedDay(lastMonth.getLastDay());
                            } else {
                                setSelectedDay(thisMonth.getDays().get(today - 1));
                            }
                            break;
                        case 38:
                            if (today <= 7) {
                                setSelectedDay(lastMonth.getDays().get(lastMonth.getDays().size() - (7 - today)));
                            } else {
                                setSelectedDay(thisMonth.getDays().get(m_selectedDay.getDay() - 7));
                            }
                            break;
                        case 39:
                            if (m_selectedDay == thisMonth.getLastDay()) {
                                setSelectedDay(nextMonth.getFirstDay());
                            } else {
                                setSelectedDay(thisMonth.getDays().get(today + 1));
                            }
                            break;
                        case 40:
                            if (today > thisMonth.getDays().size() - 7) {
                                setSelectedDay(nextMonth.getDays().get(7 - (thisMonth.getDays().size() - today)));
                            } else {
                                setSelectedDay(thisMonth.getDays().get(today + 7));
                            }
                            break;
                    }
                }
            }
        }

        /// <summary>
        /// 重绘背景方法
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public override void onPaintBackground(FCPaint paint, FCRect clipRect) {
            base.onPaintBackground(paint, clipRect);
            if (m_dayDiv != null) {
                m_dayDiv.onPaint(paint, clipRect);
            }
            if (m_monthDiv != null) {
                m_monthDiv.onPaint(paint, clipRect);
            }
            if (m_yearDiv != null) {
                m_yearDiv.onPaint(paint, clipRect);
            }
            if (m_timeDiv != null) {
                m_timeDiv.onPaint(paint, clipRect);
            }
        }

        /// <summary>
        /// 选中日期更改方法
        /// </summary>
        public virtual void onSelectedTimeChanged() {
            callEvents("onselectedtimechanged");
        }

        /// <summary>
        /// 秒表事件
        /// </summary>
        /// <param name="timerID">秒表编号</param>
        public override void onTimer(int timerID) {
            base.onTimer(timerID);
            if (m_timerID == timerID) {
                if (m_dayDiv != null) {
                    m_dayDiv.onTimer();
                }
                if (m_monthDiv != null) {
                    m_monthDiv.onTimer();
                }
                if (m_yearDiv != null) {
                    m_yearDiv.onTimer();
                }
                if (m_timeDiv != null) {
                    m_timeDiv.onTimer();
                }
            }
        }

        /// <summary>
        /// 设置属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        public override void setAttribute(String name, String value) {
            if (name == "selectedday") {
                DateTime date = Convert.ToDateTime(value);
                m_year = date.Year;
                m_month = date.Month;
                setSelectedDay(m_years.getYear(m_year).getMonths().get(m_month).getDays().get(date.Day));
            } else if (name == "useanimation") {
                setUseAnimation(FCTran.strToBool(value));
            } else {
                base.setAttribute(name, value);
            }
        }

        /// <summary>
        /// 重新布局
        /// </summary>
        public override void update() {
            base.update();
            if (m_native != null && !m_native.m_lockUpdate)
            {
                if (m_dayDiv != null)
                {
                    m_dayDiv.update();
                }
                if (m_headDiv != null)
                {
                    m_headDiv.bringToFront();
                    m_headDiv.update();
                }
                if (m_monthDiv != null)
                {
                    m_monthDiv.update();
                }
                if (m_yearDiv != null)
                {
                    m_yearDiv.update();
                }
                if (m_timeDiv != null)
                {
                    m_timeDiv.update();
                }
            }
        }

        /// <summary>
        /// 创建箭头按钮
        /// </summary>
        /// <returns>箭头按钮</returns>
        public virtual ArrowButton createArrowButton() {
            return new ArrowButton(this);
        }

        /// <summary>
        /// 创建日期标题
        /// </summary>
        /// <returns>日期标题</returns>
        public virtual DateTitle createDateTitle() {
            return new DateTitle(this);
        }

        /// <summary>
        /// 创建日的按钮
        /// </summary>
        /// <returns></returns>
        public virtual DayButton createDayButton() {
            return new DayButton(this);
        }

        /// <summary>
        /// 创建日期层
        /// </summary>
        /// <returns></returns>
        public virtual DayDiv createDayDiv() {
            return new DayDiv(this);
        }

        /// <summary>
        /// 创建头部层
        /// </summary>
        /// <returns>头部层</returns>
        public virtual HeadDiv createHeadDiv() {
            HeadDiv headDiv = new HeadDiv(this);
            headDiv.setWidth(getWidth());
            headDiv.setDock(FCDockStyle.Top);
            return headDiv;
        }

        /// <summary>
        /// 创建月的按钮
        /// </summary>
        /// <returns>月的按钮</returns>
        public virtual MonthButton createMonthButton() {
            return new MonthButton(this);
        }

        /// <summary>
        /// 创建月份的层
        /// </summary>
        /// <returns>月份层</returns>
        public virtual MonthDiv createMonthDiv() {
            return new MonthDiv(this);
        }

        /// <summary>
        /// 创建时间层
        /// </summary>
        /// <returns>时间层</returns>
        public virtual TimeDiv createTimeDiv() {
            return new TimeDiv(this);
        }

        /// <summary>
        /// 创建年的按钮
        /// </summary>
        /// <returns>年的按钮</returns>
        public virtual YearButton createYearButton() {
            return new YearButton(this);
        }

        /// <summary>
        /// 创建年的图层
        /// </summary>
        /// <returns>年图层</returns>
        public virtual YearDiv createYearDiv() {
            return new YearDiv(this);
        }
    }
}
